package com.lz.specification.reference;

import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.HashSet;
import java.util.Set;

/**
 * 软引用、弱引用、虚引用
 * 强引用!=null永   不回收 OOM
 * 软引用 内存溢出  回收
 * 弱引用 一次gc    干掉
 * 虚               gg
 *
 * 回收时放入Reference 队列 、虚引用不会
 *
 * @author: li
 * @date: 2019/1/17
 */


public class ReferenceDemo {

    private static ReferenceQueue<Grocery> rq = new ReferenceQueue<Grocery>();

    public static void checkQueue() {
        // 从队列中取出一个引用
        Reference<? extends Grocery> inq = rq.poll();
        if (inq != null){
            System.out.println("In queue: " + inq + " : " + inq.get());
    }}
    public static void main(String[] args) {
        final int size = 10;
        // 创建10个Grocery对象以及10个软引用
        Set<SoftReference<Grocery>> sa = new HashSet<>();
        for (int i = 0; i < size; i++) {
            SoftReference<Grocery> ref = new SoftReference<>(new Grocery("软引用 " + i), rq);
            System.out.println("刚刚 创建了: " + ref.get());
            sa.add(ref);
        }
        System.gc();
        checkQueue();

        // 创建10个Grocery对象以及10个弱引用
        Set<WeakReference<Grocery>> wa = new HashSet<>();
        for (int i = 0; i < size; i++) {
            WeakReference<Grocery> ref = new WeakReference<>(new Grocery("弱引用 " + i), rq);
            System.out.println("刚刚 创建了: " + ref.get());
            wa.add(ref);
        }
        System.gc();
        checkQueue();

        // 创建10个Grocery对象以及10个虚引用
        Set<PhantomReference<Grocery>> pa = new HashSet<>();
        for (int i = 0; i < size; i++) {
            PhantomReference<Grocery> ref = new PhantomReference<>(new Grocery("abc " + i), rq);
            System.out.println("刚刚 创建了: " + ref.get());
            pa.add(ref);
        }
        System.gc();
        checkQueue();
    }
}

class Grocery {
    private static final int SIZE = 10000;
    // 属性d使得每个Grocery对象占用较多内存，有80K左右
    private double[] d = new double[SIZE];
    private String id;

    public Grocery(String id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return id;
    }

    public void finalize() {
        System.out.println("即将回收 " + id);
    }
}